<?php
namespace Core\Libs\MasterView;

class MasterView extends \Core\Libs\MasterObject\MasterObject {

	protected $Helpers = NULL;
	private $helpers = array();

	protected $docType = 'loose';
	protected $layout = 'Core.Design.Layouts.default';
	protected $cssOfLayout = '.Core.Www.Css.core';
	protected $pageTitle = 'Default Page Title';
	protected $viewName = '';
	protected $classView = '';
	protected $folderNameOfViews = '';
	protected $fileNameOfDesignView = '';
	protected $designView = '';
	protected $groupOfView = 'view';
	protected $extensionOfView = 'html';
	protected $viewType = '';
	protected $groupOfLayout = 'layout';
	protected $extensionOfLayout = 'html';
	protected $responseType = 'html';
	protected $varsViewClass = array();
	protected $varsViewDesign = array();
	protected $varsLayout = array();
	protected $noLayout = FALSE;
	protected $autoRender = TRUE;
	protected $noRender = FALSE;
	protected $noScripts = FALSE;

	private $outputContent = NULL;
	private $_contentOfView = NULL;
	private $_scriptsOfView = NULL;

	private $viewDesignPath = NULL;
	private $layoutPath = NULL;

	private $_arrayFilesOfView = array();
	private $ReflectionObject = NULL;

	private $docTypes = array(

								'strict' => '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">',
								'loose' => '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">',
								'transitional' => '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">',
								'frameset' => '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">',
								'xhtml1-strict' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">',
								'xhtml1-transitional' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',
								'xhtml1-frameset' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">',
								'xhtml11' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">'
							);

	private $arrayCallbackMethods = array(
											'beforeFilter',
											'afterFilter',
											'beforeRender',
											'afterRender',
											'beforeSave',
											'afterSave',
											'beforeUpdate',
											'afterUpdate', 
											'beforeDelete', 
											'afterDelete', 
											'beforeSelect', 
											'afterSelect'
										);

	final public function &setHelper($Helper = NULL) {

		$this->Helper = $Helper;
	}

	final public function &getHelper() {

		return $this->Helper;
	}

	final public function &setHelpers(&$helpers) {

		$this->helpers = $helpers;
	}

	final public function &getHelpers() {

		return $this->helpers;
	}

	public function __construct() {

		
	}

	public function __destruct() {

		unset($this);
	}

	final public function getOutputContent() {

		return $this->outputContent;
	}

	final public function setOutputContent($content = NULL) {

		$this->outputContent = $content;
	}

	final public function &_inputCallbacksOfView() {

		
	}

	final public function &_inputCallbacksOfHelpers() {

		
	}

	final public function &_outputCallbacksOfView() {

		
	}

	final public function &_outputCallbacksOfHelpers() {

		
	}

	final public function &_callBacks($object = 'view', $type = 'input') {

		if($object === 'view') {

			if($type === 'input') {

				
			}

			elseif($type === 'output') {

				
			}
		}

		elseif($object === 'helpers') {

			if($type === 'input') {

				
			}

			elseif($type === 'output') {

				
			}
		}

		return $this;
	}

	final public static function getPropertyValue($propertyName, $context = NULL, $isStatic = NULL, $namespace = NULL, $reverse = TRUE, $first = FALSE) {

		$View = parent::getView();

		if(is_object($View)) {

			$ReflectionObject =& new \Core\Libs\Reflection\ReflectionObject(&$View);
			return $ReflectionObject->getProperty($propertyName)->getValue($context, $isStatic, $namespace, $reverse, $first);
		}

		else {

			throw \Core\Uses\exception('Error: View não é um objeto.', E_WARNING, 100, __FILE__, __LINE__);
		}
	}

	final public function _start($arrayRequest = array()) {

		$Response = parent::getResponse();
		$Response->ResponseHeader()->setOverwriteHeader(TRUE);
		$Response->ResponseHeader()->loadResponse($this->responseType);
		$typeToResponseOfRequest = $Response->getContentToResponseOfRequest();

		$View = parent::getView();
		$Controller = parent::getController();

		$namespaceBase = str_replace('\\', '.', parent::getNamespaceBase());
		$this->ReflectionObject = new \Core\Libs\Reflection\ReflectionObject($View);
		$ReflectionObjectController = new \Core\Libs\Reflection\ReflectionObject($Controller);

		$this->helpers = $this->ReflectionObject->getProperty('helpers')->mergedValuesOfMvcRequest(TRUE, FALSE);

		$this->varsViewClass = $ReflectionObjectController->getProperty('varsViewClass')->getValue(NULL, NULL, NULL, TRUE, FALSE);
		$this->varsViewDesign = $ReflectionObjectController->getProperty('varsViewDesign')->getValue(NULL, NULL, NULL, TRUE, FALSE);
		$this->varsLayout = $ReflectionObjectController->getProperty('varsLayout')->getValue(NULL, NULL, NULL, TRUE, FALSE);
		$actionOfView = $ReflectionObjectController->getProperty('actionOfView')->getValue(NULL, NULL, NULL, TRUE, FALSE);

		$this->viewName = $this->ReflectionObject->getClass()->getShortName();
		$this->classView = $this->ReflectionObject->getClass()->getName();
		$noLayoutToResquestAction = NULL;
		$return = FALSE;

		if(parent::isCalledByRequestAction()) {

			if($typeToResponseOfRequest === 'returnOfView' || $typeToResponseOfRequest === 'responseOfView') {

				$this->noRender = TRUE;
			}

			if(in_array('noLayout', (array)$arrayRequest['requestAction'])) {
echo 'akiiii';
				$noLayoutToResquestAction = TRUE;
			}

			else {

				$noLayoutToResquestAction = FALSE;
			}

			if($Response->RequestHeader()->isAjax() || in_array('return', (array)$arrayRequest['requestAction'])) {

				$return = TRUE;
			}
		}

		if(empty($actionOfView)) {

			$actionOfView = $arrayRequest['action'];
		}

		if(!$this->ReflectionObject->getMethod('namespaceForMethodPermittedExists')->invokeOfClass('Core\Libs\MasterObject\MasterObject', array($this->classView))) {

			$arrayMethodsToAction = $this->ReflectionObject->getNamesOfMethodsInClass($this->classView, array('public'), FALSE, TRUE);
			$arrayMethodsToAction = array(key($arrayMethodsToAction) => array_diff((array)current($arrayMethodsToAction), $this->arrayCallbackMethods));
			$this->ReflectionObject->getMethod('addMethodsAllowed')->invokeOfClass('Core\Libs\MasterObject\MasterObject', array($arrayMethodsToAction, $this->classView));
			unset($arrayMethodsToAction);
		}

		$isAllowedViewAction = $this->ReflectionObject->getMethod('isMethodAllowed')->invokeOfClass('Core\Libs\MasterObject\MasterObject', array($this->classView, $actionOfView));

		if($isAllowedViewAction) {

			if(parent::isValidAction($actionOfView)) {

				if($typeToResponseOfRequest === 'returnOfView') {

					ob_start();
					$this->beforeFilter();
					$this->outputContent = $View->$actionOfView();
					$this->afterFilter();
					ob_end_clean();

					if($Response->isAllContentToResponseOfRequest()) {

						$this->outputContent = ob_get_clean() . $this->outputContent;
					}
				}

				elseif($typeToResponseOfRequest === 'responseOfView') {

					ob_start();
					$this->beforeFilter();
					$View->$actionOfView();
					$this->afterFilter();
					$this->outputContent = ob_get_clean();

					if($Response->isAllContentToResponseOfRequest()) {

						$this->outputContent = ob_get_clean() . $this->outputContent;
					}
				}

				else {

					ob_start();
					$this->beforeFilter();
					$View->$actionOfView();
					$this->afterFilter();
					$this->outputContent = ob_get_clean();

					if(!$Response->isAllContentToResponseOfRequest()) {

						$this->outputContent = ob_get_clean() . $this->outputContent;
					}
				}
			}
		}

		else {

			throw \Core\Uses\Exception('Error: Action não encontrada na View. - View: ' . $this->classView . ', Action: ' . $actionOfView);
		}

		if($return) {

			$this->autoRender = FALSE;
		}

		if($typeToResponseOfRequest === 'responseOfRequest' && $Response->isAllContentToResponseOfRequest()) {

			$this->autoRender = TRUE;
		}

		//$this->noScripts = $this->ReflectionObject->getProperty('noScripts')->getValue(NULL, NULL, NULL, FALSE, FALSE);
		//$this->groupOfLayout = $this->ReflectionObject->getProperty('groupOfLayout')->getValue(NULL, NULL, NULL, FALSE, FALSE);
		//$this->groupOfView = $this->ReflectionObject->getProperty('groupOfView')->getValue(NULL, NULL, NULL, FALSE, FALSE);
		//$this->extensionOfLayout = $this->ReflectionObject->getProperty('extensionOfLayout')->getValue(NULL, NULL, NULL, FALSE, FALSE);
		//$this->extensionOfView = $this->ReflectionObject->getProperty('extensionOfView')->getValue(NULL, NULL, NULL, FALSE, FALSE);
		//$this->layout = $this->ReflectionObject->getProperty('layout')->getValue(NULL, NULL, NULL, FALSE, FALSE);
		//$this->designView = $this->ReflectionObject->getProperty('designView')->getValue(NULL, NULL, NULL, FALSE, FALSE);

		if(!$this->noRender) {

			if(!$Response->isAllContentToResponseOfRequest()) {

				$this->outputContent = NULL;
			}

			if($noLayoutToResquestAction !== NULL) {

				$this->noLayout = $noLayoutToResquestAction;
			}

			if(empty($this->extensionOfView)) {

				$this->extensionOfView = $this->responseType;
			}

			if(empty($this->designView)) {

				//$this->folderNameOfViews = $this->ReflectionObject->getProperty('folderNameOfViews')->getValue(NULL, NULL, NULL, FALSE, FALSE);
				//$this->fileNameOfDesignView = $this->ReflectionObject->getProperty('fileNameOfDesignView')->getValue(NULL, NULL, NULL, FALSE, FALSE);
				$this->fileNameOfDesignView = $actionOfView;

				if(empty($this->folderNameOfViews)) {

					$this->folderNameOfViews = parent::getRequest()->getElement(array('controller', 'class', 'controllerName'));

					if(empty($this->folderNameOfViews)) {

						$this->folderNameOfViews = $this->viewName;
					}
				}

				if(empty($this->fileNameOfDesignView)) {

					$this->fileNameOfDesignView = 'index';
				}

				$this->designView = '(@design.' . $this->groupOfView . '.' . $this->extensionOfView . ')' . $namespaceBase . 'design.views.' . $this->folderNameOfViews . '.' . $this->fileNameOfDesignView;
			}

			else {

				if($this->designView{0} !== '(' || !$this->designView{0} !== '[') {
	
					$this->designView = '(@design.' . $this->groupOfView . '.' . $this->extensionOfView . ')' . $this->designView;
				}
			}

			if(empty($this->extensionOfLayout)) {

				$this->extensionOfLayout = $this->responseType;
			}

			if($this->layout{0} !== '(' || !$this->layout{0} !== '[') {

				$this->layout = '(@design.' . $this->groupOfLayout . '.' . $this->extensionOfLayout . ')' . $this->layout;
			}

			parent::getRequest()->addElement(array('views', 'class'), array('path' => $arrayRequest['view']['path'], 'namespace' => $arrayRequest['view']['namespace'], 'designView' => $this->designView));

			if($this->noLayout) {

				$this->outputContent .= $this->_renderView($this->designView, NULL);
			}

			else {

				$this->outputContent .= $this->_renderView($this->designView, $this->layout);
			}
		}

		if($this->autoRender === TRUE) {

			echo($this->outputContent);
			$this->outputContent = NULL;
		}

		else {

			$this->autoRender = FALSE;
		}

		return;
	}

	private function &_removeFilesOfView($string = NULL, $type = 'css') {

		if(in_array(&$string, (array)$this->_arrayFilesOfView[$type])) {

			unset($this->_arrayFilesOfView[$type][$string]);
		}
	}

	final public function &_addFilesOfView($string = NULL, $type = 'css', $extension = 'css') {

		if($this->noScripts) {

			return;
		}

		if(!preg_match('/^http/i', &$string)) {

			if($type === 'css') {

				$path = parent::getRegistry()->getPathOfCss(&$string);
			}

			elseif($type === 'js') {

				$path = parent::getRegistry()->getPathOfJavascript(&$string);
			}

			$string =& mb_strtolower(&$string);
			$path = str_replace(DS, '/', DS . preg_replace('/^'.addslashes(DOCUMENT_ROOT).'/i', '', &$path));
		}

		else {

			$path =& $string;
		}

		if(!in_array(&$string, (array)$this->_arrayFilesOfView[$type])) {

			$this->_arrayFilesOfView[$type][$string] =& $path;
		}
	}

	final public function getImage($string = NULL, $type = 'jpg', $options = array()) {

		$string = str_replace(DS, '/', DS . preg_replace('/^'.addslashes(DOCUMENT_ROOT).'/i', '', parent::getRegistry()->getPathOfImage(&$string, &$type)));

		if($options === TRUE) {

			if($string === '/') {

				$string = '';
			}

			return $string;
		}

		elseif(is_array(&$options)) {

			$tag = '<img';

			foreach($options as $key => $value) {

				$tag .= ' ' . $key . '=' . '"' .$value . '"';
			}

			if(!empty($string) && $string !== '/') {

				$tag .= ' src=' . '"' . $string . '" />';
			}

			else {

				$tag .= ' src="" />';
			}

			$string = $tag;
			unset($tag, $key, $value, $options);
		}

		return $string;
	}

	final public function &addCss($string = NULL) {

		$this->_addFilesOfView(&$string, 'css');
	}

	final public function &removeCss($string = NULL) {

		$this->_removeFilesOfView(&$string, 'css');
	}

	final public function &getCss() {

		return $this->_arrayFilesOfView['css'];
	}

	final public function &getCssOfLayout() {

		$string = '';

		if(is_array($this->_arrayFilesOfView['css'])) {

			foreach($this->_arrayFilesOfView['css'] as $file) {

				$string .= '<link rel="stylesheet" type="text/css" href="'.$file.'"/>'."\n";
			}
		}

		return $string;
	}

	final public function &addJavascript($string = NULL) {

		$this->_addFilesOfView(&$string, 'js');
	}

	final public function &removeJavascript($string = NULL) {

		$this->_removeFilesOfView(&$string, 'js');
	}

	final public function &getJavascriptOfLayout() {

		$string = '';

		if(is_array($this->_arrayFilesOfView['js'])) {

			foreach($this->_arrayFilesOfView['js'] as $file) {

				$string .= '<script type="text/javascript" language="javascript" src="'.$file.'"></script>'."\n";
			}
		}

		return $string;
	}

	final public function &getJavascript() {

		return $this->_arrayFilesOfView['js'];
	}

	final public function &getPageTitle($html = TRUE) {

		if($html === TRUE) {

			return '<title>'.$this->pageTitle.'</title>'."\n";
		}

		return $this->pageTitle;
	}

	final public function getDocType() {

		return $this->docTypes[$this->docType];
	}

	final public static function getBrowser() {

		return \Core\Uses\getBrowser();
	}

	final public static function getBrowserVersion() {

		return \Core\Uses\getBrowserVersion();
	}

	final public function _render($file = NULL, $sendData = array(), $type = 'view') {

		if(!empty($file)) {

			$output = NULL;
			extract(&$sendData, EXTR_REFS & EXTR_SKIP);

			ob_start();

			if($type === 'layout') {

				$this->beforeRender();
			}

			@include($file);

			if($type === 'layout') {

				$this->afterRender();
			}

			$output = ob_get_clean();

			return $output;
		}

		return FALSE;
	} 

	final public function _renderView($stringViewDesign, $stringLayout = NULL) {

		$match = array();
		$RegistryClass =& parent::getRegistry();
		$viewDesignPath =& $RegistryClass->getPathOfViewDesign($stringViewDesign, 'default', 'view', FALSE);

		if($viewDesignPath === FALSE) {

			throw \Core\Uses\Exception('Error: Arquivo View (Design) não encontrada. - Path: '.$viewDesignPath);
		}

		else {

			$this->_viewDesignPath =& $viewDesignPath;
			$output = $this->_render($viewDesignPath, 
														array_merge(

														(array)self::$sharedRequestVars,
														(array)self::$sharedVars,
														(array)$this->varsViewDesign,

														array(

														'Model' => parent::getModel(),
														'View' => parent::getView(),
														'Controller' => parent::getController(),
														'Component' => parent::getController()->getComponent(),
														'Helper' => parent::getView()->getHelper(),
														'Behavior' => NULL)
														), 'view');

			if(!$output) {

				throw \Core\Uses\Exception('Error: Erro na View. - Path: ' . $viewDesignPath);
			}
		}

		if(!empty($stringLayout)) {

			$output = $this->_renderLayout($output, $stringLayout);
		}

		return $output;
	}

	final public function _renderLayout($output = NULL, $stringLayout = NULL) {

		$RegistryClass = parent::getRegistry();
		$cssOfLayout = $this->ReflectionObject->getProperty('cssOfLayout')->getValue(NULL, NULL, NULL, FALSE, FALSE);
		$this->addCss($cssOfLayout);
		$this->addJavascript('.Core.Www.js.jquery');
		$this->addJavascript('.Core.Www.js.core');

		(empty($stringLayout)) ? $pathLayout = $RegistryClass->getPathOfLayout($this->layout) : $pathLayout = $RegistryClass->getPathOfLayout($stringLayout);

		if($pathLayout !== FALSE) {

			parent::getRequest()->getElement(array('layout', 'path'), $pathLayout);
			$this->layoutPath = $pathLayout;
			$output = $this->_render(&$pathLayout, 

													array_merge(

													(array)self::$sharedRequestVars,
													(array)self::$sharedVars,
													(array)$this->varsLayout,

													array('_contentOfLayout' => $output)), 'layout');

			if(!$output) {

				throw \Core\Uses\Exception('Error: Erro no Layout. - Path: ' . $pathLayout);
			}
		}

		else {

			throw \Core\Uses\Exception('Error: Arquivo de Layout não encontrado.');
		}

		return $output;
	}

	final public function &_flush() {

	}

	public function &render() {

		$this->_flush();
	}

	public function &renderElement() {

		
	}

	public function disableCache() {

		header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
		header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
		header('Cache-Control: no-store, no-cache, must-revalidate');
		header('Cache-Control: post-check=0, pre-check=0', FALSE);
		header('Pragma: no-cache');
	}

	public function beforeRender() {

	}

	public function afterRender() {

	}

	public function beforeFilter() {

		
	}

	public function afterFilter() {

		
	}
}
?>